<!--
> Muaz Khan     - www.MuazKhan.com
> MIT License   - www.WebRTC-Experiment.com/licence
> Documentation - github.com/muaz-khan/RecordRTC
> and           - RecordRTC.org
-->
<!DOCTYPE html>
<html lang="en">

<head>
    <title>RecordRTC | WebRTC Audio+Video+Screen Recording</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

    <link rel="stylesheet" href="https://www.webrtc-experiment.com/style.css">

    <style>
        li {
            border-bottom: 1px solid rgb(189, 189, 189);
            border-left: 1px solid rgb(189, 189, 189);
            padding: .5em;
        }
        label {
            display: inline-block;
            width: 8em;
        }

        h1 span {
            background: yellow;
            border: 2px solid #8e1515;
            padding: 2px 8px;
            margin: 2px 5px;
            border-radius: 7px;
            color: #8e1515;
            display: inline-block;
        }

        .recordrtc button {
            font-size: inherit;
        }

        .recordrtc button, .recordrtc select {
            vertical-align: middle;
            line-height: 1;
            padding: 2px 5px;
            height: auto;
            font-size: inherit;
            margin: 0;
        }

        .recordrtc, .recordrtc .header {
            display: block;
            text-align: center;
            padding-top: 0;
        }

        .recordrtc video, .recordrtc img {
            max-width: 100%!important;
            vertical-align: top;
        }

        .recordrtc audio {
            vertical-align: bottom;
        }

        .recordrtc option[disabled] {
            display: none;
        }

        .recordrtc select {
            font-size: 17px;
        }
    </style>

    <script src="/RecordRTC.js"></script>
    
    <!-- web streams API polyfill to support Firefox -->
    <script src="https://unpkg.com/@mattiasbuelens/web-streams-polyfill/dist/polyfill.min.js"></script>

    <!-- ../libs/DBML.js to fix video seeking issues -->
    <script src="https://www.webrtc-experiment.com/EBML.js"></script>

    <!-- for Edge/FF/Chrome/Opera/etc. getUserMedia support -->
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="https://www.webrtc-experiment.com/DetectRTC.js"> </script>

    <!-- video element -->
    <link href="https://www.webrtc-experiment.com/getHTMLMediaElement.css" rel="stylesheet">
    <script src="https://www.webrtc-experiment.com/getHTMLMediaElement.js"></script>
</head>

<body>
    <article>
        <header style="text-align: center;">
            <h1>
                Audio+Video+Screen Recording using <a href="https://github.com/muaz-khan/RecordRTC">RecordRTC</a>
            </h1>

            <p style="margin:0;margin-bottom:-30px;margin-top: 15px;">
                <a href="https://github.com/muaz-khan/RecordRTC">Github Source Codes</a> |
                <a href="Canvas-Recording/">Canvas Recording</a> |
                <a href="simple-demos/" style="color: #EC008C;border: 1px dotted;background: #ffffbe;padding: 0 6px;border-radius: 3px;">30+ Simple Demos</a>

                <br><br>

                <a href="https://www.npmjs.com/package/recordrtc"><img src="https://img.shields.io/npm/v/recordrtc.svg"></a>
                <a href="https://www.npmjs.com/package/recordrtc"><img src="https://img.shields.io/npm/dm/recordrtc.svg"></a>
                <a href="https://travis-ci.org/muaz-khan/RecordRTC"><img src="https://travis-ci.org/muaz-khan/RecordRTC.png?branch=master"></a>
            </p>
        </header>

        <div class="github-stargazers" style="margin-top: 25px;"></div>

        <section class="experiment recordrtc">
            <h2 class="header" style="margin: 0;">
                <select class="recording-media">
                    <option value="record-audio-plus-video">Microphone+Camera</option>
                    <option value="record-audio">Microphone</option>
                    <option value="record-screen">Full Screen</option>
                    <option value="record-audio-plus-screen">Microphone+Screen</option>
                </select>

                <span style="font-size: 15px;">into</span>

                <select class="media-container-format">
                    <option>default</option>
                    <option>vp8</option>
                    <option>vp9</option>
                    <option>h264</option>
                    <option>mkv</option>
                    <option>opus</option>
                    <option>ogg</option>
                    <option>pcm</option>
                    <option>gif</option>
                    <option>whammy</option>
                    <option>WebAssembly</option>
                </select>

                <input type="checkbox" id="chk-timeSlice" style="margin:0;width:auto;" title="Use intervals based recording">
                <label for="chk-timeSlice" style="font-size: 15px;margin:0;width: auto;cursor: pointer;-webkit-user-select:none;user-select:none;" title="Use intervals based recording">Use timeSlice?</label>

                <br>

                <button id="btn-start-recording">Start Recording</button>
                <button id="btn-pause-recording" style="display: none; font-size: 15px;">Pause</button>

                <div style="display: inline-block;">
                    <input type="checkbox" id="chk-fixSeeking" style="margin:0;width:auto;" title="Fix video seeking issues?">
                    <label for="chk-fixSeeking" style="font-size: 15px;margin:0;width: auto;cursor: pointer;-webkit-user-select:none;user-select:none;" title="Fix video seeking issues?">Fix Seeking Issues?</label>
                </div>

                <hr style="border-top: 0;border-bottom: 1px solid rgb(189, 189, 189);margin: 4px -12px;margin-top: 8px;">
                <select class="media-resolutions">
                    <option value="default">Default resolutions</option>
                    <option value="1920x1080">1080p</option>
                    <option value="1280x720">720p</option>
                    <option value="640x480">480p</option>
                    <option value="3840x2160">4K Ultra HD (3840x2160)</option>
                </select>

                <select class="media-framerates">
                    <option value="default">Default framerates</option>
                    <option value="5">5 fps</option>
                    <option value="15">15 fps</option>
                    <option value="24">24 fps</option>
                    <option value="30">30 fps</option>
                    <option value="60">60 fps</option>
                </select>

                <select class="media-bitrates">
                    <option value="default">Default bitrates</option>
                    <option value="8000000000">1 GB bps</option>
                    <option value="800000000">100 MB bps</option>
                    <option value="8000000">1 MB bps</option>
                    <option value="800000">100 KB bps</option>
                    <option value="8000">1 KB bps</option>
                    <option value="800">100 Bytes bps</option>
                </select>
            </h2>

            <div style="text-align: center; display: none;">
                <button id="save-to-disk">Save To Disk</button>
                <button id="upload-to-php">Upload to PHP</button>
                <button id="open-new-tab">Open New Tab</button>

                <div style="margin-top: 10px;">
                    <span id="signinButton" class="pre-sign-in">
                      <span
                        class="g-signin"
                        data-callback="signinCallback"
                        data-clientid="41556190767-115ifahd55lk4ln5pop4jus55cr4l7oh.apps.googleusercontent.com"
                        data-cookiepolicy="single_host_origin"
                        data-scope="https://www.googleapis.com/auth/youtube.upload https://www.googleapis.com/auth/youtube">
                      </span>
                    </span>

                    <button id="upload-to-youtube" style="vertical-align:top;">Upload to YouTube</button>
                </div>
            </div>

            <div style="margin-top: 10px;" id="recording-player"></div>
        </section>

        <script>
            (function() {
                var params = {},
                    r = /([^&=]+)=?([^&]*)/g;

                function d(s) {
                    return decodeURIComponent(s.replace(/\+/g, ' '));
                }

                var match, search = window.location.search;
                while (match = r.exec(search.substring(1))) {
                    params[d(match[1])] = d(match[2]);

                    if(d(match[2]) === 'true' || d(match[2]) === 'false') {
                        params[d(match[1])] = d(match[2]) === 'true' ? true : false;
                    }
                }

                window.params = params;
            })();

            function addStreamStopListener(stream, callback) {
                stream.addEventListener('ended', function() {
                    callback();
                    callback = function() {};
                }, false);
                stream.addEventListener('inactive', function() {
                    callback();
                    callback = function() {};
                }, false);
                stream.getTracks().forEach(function(track) {
                    track.addEventListener('ended', function() {
                        callback();
                        callback = function() {};
                    }, false);
                    track.addEventListener('inactive', function() {
                        callback();
                        callback = function() {};
                    }, false);
                });
            }
        </script>

        <script>
            var video = document.createElement('video');
            video.controls = false;
            var mediaElement = getHTMLMediaElement(video, {
                title: 'Recording status: inactive',
                buttons: ['full-screen'/*, 'take-snapshot'*/],
                showOnMouseEnter: false,
                width: 360,
                onTakeSnapshot: function() {
                    var canvas = document.createElement('canvas');
                    canvas.width = mediaElement.clientWidth;
                    canvas.height = mediaElement.clientHeight;

                    var context = canvas.getContext('2d');
                    context.drawImage(recordingPlayer, 0, 0, canvas.width, canvas.height);

                    window.open(canvas.toDataURL('image/png'));
                }
            });
            document.getElementById('recording-player').appendChild(mediaElement);

            var div = document.createElement('section');
            mediaElement.media.parentNode.appendChild(div);
            mediaElement.media.muted = false;
            mediaElement.media.autoplay = true;
            mediaElement.media.playsinline = true;
            div.appendChild(mediaElement.media);
            
            var recordingPlayer = mediaElement.media;
            var recordingMedia = document.querySelector('.recording-media');
            var mediaContainerFormat = document.querySelector('.media-container-format');
            var mimeType = 'video/webm';
            var fileExtension = 'webm';
            var type = 'video';
            var recorderType;
            var defaultWidth;
            var defaultHeight;

            var btnStartRecording = document.querySelector('#btn-start-recording');

            window.onbeforeunload = function() {
                btnStartRecording.disabled = false;
                recordingMedia.disabled = false;
                mediaContainerFormat.disabled = false;

                chkFixSeeking.parentNode.style.display = 'inline-block';
            };

            btnStartRecording.onclick = function(event) {
                var button = btnStartRecording;

                if(button.innerHTML === 'Stop Recording') {
                    btnPauseRecording.style.display = 'none';
                    button.disabled = true;
                    button.disableStateWaiting = true;
                    setTimeout(function() {
                        button.disabled = false;
                        button.disableStateWaiting = false;
                    }, 2000);

                    button.innerHTML = 'Start Recording';

                    function stopStream() {
                        if(button.stream && button.stream.stop) {
                            button.stream.stop();
                            button.stream = null;
                        }

                        if(button.stream instanceof Array) {
                            button.stream.forEach(function(stream) {
                                stream.stop();
                            });
                            button.stream = null;
                        }

                        videoBitsPerSecond = null;
                        var html = 'Recording status: stopped';
                        html += '<br>Size: ' + bytesToSize(button.recordRTC.getBlob().size);
                        recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = html;
                    }

                    if(button.recordRTC) {
                        if(button.recordRTC.length) {
                            button.recordRTC[0].stopRecording(function(url) {
                                if(!button.recordRTC[1]) {
                                    button.recordingEndedCallback(url);
                                    stopStream();

                                    saveToDiskOrOpenNewTab(button.recordRTC[0]);
                                    return;
                                }

                                button.recordRTC[1].stopRecording(function(url) {
                                    button.recordingEndedCallback(url);
                                    stopStream();
                                });
                            });
                        }
                        else {
                            button.recordRTC.stopRecording(function(url) {
                                if(button.blobs && button.blobs.length) {
                                    var blob = new File(button.blobs, getFileName(fileExtension), {
                                        type: mimeType
                                    });
                                    
                                    button.recordRTC.getBlob = function() {
                                        return blob;
                                    };

                                    url = URL.createObjectURL(blob);
                                }

                                if(chkFixSeeking.checked === true) {
                                    // to fix video seeking issues
                                    getSeekableBlob(button.recordRTC.getBlob(), function(seekableBlob) {
                                        button.recordRTC.getBlob = function() {
                                            return seekableBlob;
                                        };

                                        url = URL.createObjectURL(seekableBlob);

                                        button.recordingEndedCallback(url);
                                        saveToDiskOrOpenNewTab(button.recordRTC);
                                        stopStream();
                                    })
                                    return;
                                }

                                button.recordingEndedCallback(url);
                                saveToDiskOrOpenNewTab(button.recordRTC);
                                stopStream();
                            });
                        }
                    }

                    return;
                }

                if(!event) return;

                button.disabled = true;

                var commonConfig = {
                    onMediaCaptured: function(stream) {
                        button.stream = stream;
                        if(button.mediaCapturedCallback) {
                            button.mediaCapturedCallback();
                        }

                        button.innerHTML = 'Stop Recording';
                        button.disabled = false;

                        chkFixSeeking.parentNode.style.display = 'none';
                    },
                    onMediaStopped: function() {
                        button.innerHTML = 'Start Recording';

                        if(!button.disableStateWaiting) {
                            button.disabled = false;
                        }

                        chkFixSeeking.parentNode.style.display = 'inline-block';
                    },
                    onMediaCapturingFailed: function(error) {
                        console.error('onMediaCapturingFailed:', error);

                        if(error.toString().indexOf('no audio or video tracks available') !== -1) {
                            alert('RecordRTC failed to start because there are no audio or video tracks available.');
                        }
                        
                        if(error.name === 'PermissionDeniedError' && DetectRTC.browser.name === 'Firefox') {
                            alert('Firefox requires version >= 52. Firefox also requires HTTPs.');
                        }

                        commonConfig.onMediaStopped();
                    }
                };

                if(mediaContainerFormat.value === 'h264') {
                    mimeType = 'video/webm\;codecs=h264';
                    fileExtension = 'mp4';

                    // video/mp4;codecs=avc1    
                    if(isMimeTypeSupported('video/mpeg')) {
                        mimeType = 'video/mpeg';
                    }
                }

                if(mediaContainerFormat.value === 'mkv' && isMimeTypeSupported('video/x-matroska;codecs=avc1')) {
                    mimeType = 'video/x-matroska;codecs=avc1';
                    fileExtension = 'mkv';
                }

                if(mediaContainerFormat.value === 'vp8' && isMimeTypeSupported('video/webm\;codecs=vp8')) {
                    mimeType = 'video/webm\;codecs=vp8';
                    fileExtension = 'webm';
                    recorderType = null;
                    type = 'video';
                }

                if(mediaContainerFormat.value === 'vp9' && isMimeTypeSupported('video/webm\;codecs=vp9')) {
                    mimeType = 'video/webm\;codecs=vp9';
                    fileExtension = 'webm';
                    recorderType = null;
                    type = 'video';
                }

                if(mediaContainerFormat.value === 'pcm') {
                    mimeType = 'audio/wav';
                    fileExtension = 'wav';
                    recorderType = StereoAudioRecorder;
                    type = 'audio';
                }

                if(mediaContainerFormat.value === 'opus' || mediaContainerFormat.value === 'ogg') {
                    if(isMimeTypeSupported('audio/webm')) {
                        mimeType = 'audio/webm';
                        fileExtension = 'webm'; // webm
                    }

                    if(isMimeTypeSupported('audio/ogg')) {
                        mimeType = 'audio/ogg; codecs=opus';
                        fileExtension = 'ogg'; // ogg
                    }

                    recorderType = null;
                    type = 'audio';
                }

                if(mediaContainerFormat.value === 'whammy') {
                    mimeType = 'video/webm';
                    fileExtension = 'webm';
                    recorderType = WhammyRecorder;
                    type = 'video';
                }

                if(mediaContainerFormat.value === 'WebAssembly') {
                    mimeType = 'video/webm';
                    fileExtension = 'webm';
                    recorderType = WebAssemblyRecorder;
                    type = 'video';
                }

                if(mediaContainerFormat.value === 'gif') {
                    mimeType = 'image/gif';
                    fileExtension = 'gif';
                    recorderType = GifRecorder;
                    type = 'gif';
                }

                if(mediaContainerFormat.value === 'default') {
                    mimeType = 'video/webm';
                    fileExtension = 'webm';
                    recorderType = null;
                    type = 'video';
                }

                if(recordingMedia.value === 'record-audio') {
                    captureAudio(commonConfig);

                    button.mediaCapturedCallback = function() {
                        var options = {
                            type: type,
                            mimeType: mimeType,
                            leftChannel: params.leftChannel || false,
                            disableLogs: params.disableLogs || false
                        };

                        if(params.sampleRate) {
                            options.sampleRate = parseInt(params.sampleRate);
                        }

                        if(params.bufferSize) {
                            options.bufferSize = parseInt(params.bufferSize);
                        }

                        if(recorderType) {
                            options.recorderType = recorderType;
                        }

                        if(videoBitsPerSecond) {
                            options.videoBitsPerSecond = videoBitsPerSecond;
                        }

                        if(DetectRTC.browser.name === 'Edge') {
                            options.numberOfAudioChannels = 1;
                        }

                        options.ignoreMutedMedia = false;
                        button.recordRTC = RecordRTC(button.stream, options);

                        button.recordingEndedCallback = function(url) {
                            setVideoURL(url);
                        };

                        button.recordRTC.startRecording();
                        btnPauseRecording.style.display = '';
                    };
                }

                if(recordingMedia.value === 'record-audio-plus-video') {
                    captureAudioPlusVideo(commonConfig);

                    button.mediaCapturedCallback = function() {
                        if(typeof MediaRecorder === 'undefined') { // opera or chrome etc.
                            button.recordRTC = [];

                            if(!params.bufferSize) {
                                // it fixes audio issues whilst recording 720p
                                params.bufferSize = 16384;
                            }

                            var options = {
                                type: 'audio', // hard-code to set "audio"
                                leftChannel: params.leftChannel || false,
                                disableLogs: params.disableLogs || false,
                                video: recordingPlayer
                            };

                            if(params.sampleRate) {
                                options.sampleRate = parseInt(params.sampleRate);
                            }

                            if(params.bufferSize) {
                                options.bufferSize = parseInt(params.bufferSize);
                            }

                            if(params.frameInterval) {
                                options.frameInterval = parseInt(params.frameInterval);
                            }

                            if(recorderType) {
                                options.recorderType = recorderType;
                            }

                            if(videoBitsPerSecond) {
                                options.videoBitsPerSecond = videoBitsPerSecond;
                            }

                            options.ignoreMutedMedia = false;
                            var audioRecorder = RecordRTC(button.stream, options);

                            options.type = type;
                            var videoRecorder = RecordRTC(button.stream, options);

                            // to sync audio/video playbacks in browser!
                            videoRecorder.initRecorder(function() {
                                audioRecorder.initRecorder(function() {
                                    audioRecorder.startRecording();
                                    videoRecorder.startRecording();
                                    btnPauseRecording.style.display = '';
                                });
                            });

                            button.recordRTC.push(audioRecorder, videoRecorder);

                            button.recordingEndedCallback = function() {
                                var audio = new Audio();
                                audio.src = audioRecorder.toURL();
                                audio.controls = true;
                                audio.autoplay = true;

                                recordingPlayer.parentNode.appendChild(document.createElement('hr'));
                                recordingPlayer.parentNode.appendChild(audio);

                                if(audio.paused) audio.play();
                            };
                            return;
                        }

                        var options = {
                            type: type,
                            mimeType: mimeType,
                            disableLogs: params.disableLogs || false,
                            getNativeBlob: false, // enable it for longer recordings
                            video: recordingPlayer
                        };

                        if(recorderType) {
                            options.recorderType = recorderType;

                            if(recorderType == WhammyRecorder || recorderType == GifRecorder || recorderType == WebAssemblyRecorder) {
                                options.canvas = options.video = {
                                    width: defaultWidth || 320,
                                    height: defaultHeight || 240
                                };
                            }
                        }

                        if(videoBitsPerSecond) {
                            options.videoBitsPerSecond = videoBitsPerSecond;
                        }

                        if(timeSlice && typeof MediaRecorder !== 'undefined') {
                            options.timeSlice = timeSlice;
                            button.blobs = [];
                            options.ondataavailable = function(blob) {
                                button.blobs.push(blob);
                            };
                        }

                        options.ignoreMutedMedia = false;
                        button.recordRTC = RecordRTC(button.stream, options);

                        button.recordingEndedCallback = function(url) {
                            setVideoURL(url);
                        };

                        button.recordRTC.startRecording();
                        btnPauseRecording.style.display = '';
                        recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = '<img src="https://www.webrtc-experiment.com/images/progress.gif">';
                    };
                }

                if(recordingMedia.value === 'record-screen') {
                    captureScreen(commonConfig);

                    button.mediaCapturedCallback = function() {
                        var options = {
                            type: type,
                            mimeType: mimeType,
                            disableLogs: params.disableLogs || false,
                            getNativeBlob: false, // enable it for longer recordings
                            video: recordingPlayer
                        };

                        if(recorderType) {
                            options.recorderType = recorderType;

                            if(recorderType == WhammyRecorder || recorderType == GifRecorder || recorderType == WebAssemblyRecorder) {
                                options.canvas = options.video = {
                                    width: defaultWidth || 320,
                                    height: defaultHeight || 240
                                };
                            }
                        }

                        if(videoBitsPerSecond) {
                            options.videoBitsPerSecond = videoBitsPerSecond;
                        }

                        options.ignoreMutedMedia = false;
                        button.recordRTC = RecordRTC(button.stream, options);

                        button.recordingEndedCallback = function(url) {
                            setVideoURL(url);
                        };

                        button.recordRTC.startRecording();
                        btnPauseRecording.style.display = '';
                    };
                }

                // note: audio+tab is supported in Chrome 50+
                // todo: add audio+tab recording
                if(recordingMedia.value === 'record-audio-plus-screen') {
                    captureAudioPlusScreen(commonConfig);

                    button.mediaCapturedCallback = function() {
                        var options = {
                            type: type,
                            mimeType: mimeType,
                            disableLogs: params.disableLogs || false,
                            getNativeBlob: false, // enable it for longer recordings
                            video: recordingPlayer
                        };

                        if(recorderType) {
                            options.recorderType = recorderType;

                            if(recorderType == WhammyRecorder || recorderType == GifRecorder || recorderType == WebAssemblyRecorder) {
                                options.canvas = options.video = {
                                    width: defaultWidth || 320,
                                    height: defaultHeight || 240
                                };
                            }
                        }

                        if(videoBitsPerSecond) {
                            options.videoBitsPerSecond = videoBitsPerSecond;
                        }

                        options.ignoreMutedMedia = false;
                        button.recordRTC = RecordRTC(button.stream, options);

                        button.recordingEndedCallback = function(url) {
                            setVideoURL(url);
                        };

                        button.recordRTC.startRecording();
                        btnPauseRecording.style.display = '';
                    };
                }
            };

            function captureVideo(config) {
                captureUserMedia({video: true}, function(videoStream) {
                    config.onMediaCaptured(videoStream);

                    addStreamStopListener(videoStream, function() {
                        config.onMediaStopped();
                    });
                }, function(error) {
                    config.onMediaCapturingFailed(error);
                });
            }

            function captureAudio(config) {
                captureUserMedia({audio: true}, function(audioStream) {
                    config.onMediaCaptured(audioStream);

                    addStreamStopListener(audioStream, function() {
                        config.onMediaStopped();
                    });
                }, function(error) {
                    config.onMediaCapturingFailed(error);
                });
            }

            function captureAudioPlusVideo(config) {
                captureUserMedia({video: true, audio: true}, function(audioVideoStream) {
                    config.onMediaCaptured(audioVideoStream);

                    if(audioVideoStream instanceof Array) {
                        audioVideoStream.forEach(function(stream) {
                            addStreamStopListener(stream, function() {
                                config.onMediaStopped();
                            });
                        });
                        return;
                    }

                    addStreamStopListener(audioVideoStream, function() {
                        config.onMediaStopped();
                    });
                }, function(error) {
                    config.onMediaCapturingFailed(error);
                });
            }

            var MY_DOMAIN = 'webrtc-experiment.com';

            function isMyOwnDomain() {
                // replace "webrtc-experiment.com" with your own domain name
                return document.domain.indexOf(MY_DOMAIN) !== -1;
            }

            function isLocalHost() {
                // "chrome.exe" --enable-usermedia-screen-capturing
                // or firefox => about:config => "media.getusermedia.screensharing.allowed_domains" => add "localhost"
                return document.domain === 'localhost' || document.domain === '127.0.0.1';
            }

            var videoBitsPerSecond;

            function setVideoBitrates() {
                var select = document.querySelector('.media-bitrates');
                var value = select.value;

                if(value == 'default') {
                    videoBitsPerSecond = null;
                    return;
                }

                videoBitsPerSecond = parseInt(value);
            }

            function getFrameRates(mediaConstraints) {
                if(!mediaConstraints.video) {
                    return mediaConstraints;
                }

                var select = document.querySelector('.media-framerates');
                var value = select.value;

                if(value == 'default') {
                    return mediaConstraints;
                }

                value = parseInt(value);

                if(DetectRTC.browser.name === 'Firefox') {
                    mediaConstraints.video.frameRate = value;
                    return mediaConstraints;
                }

                if(!mediaConstraints.video.mandatory) {
                    mediaConstraints.video.mandatory = {};
                    mediaConstraints.video.optional = [];
                }

                var isScreen = recordingMedia.value.toString().toLowerCase().indexOf('screen') != -1;
                if(isScreen) {
                    mediaConstraints.video.mandatory.maxFrameRate = value;
                }
                else {
                    mediaConstraints.video.mandatory.minFrameRate = value;
                }

                return mediaConstraints;
            }

            function setGetFromLocalStorage(selectors) {
                selectors.forEach(function(selector) {
                    var storageItem = selector.replace(/\.|#/g, '');
                    if(localStorage.getItem(storageItem)) {
                        document.querySelector(selector).value = localStorage.getItem(storageItem);
                    }

                    addEventListenerToUploadLocalStorageItem(selector, ['change', 'blur'], function() {
                        localStorage.setItem(storageItem, document.querySelector(selector).value);
                    });
                });
            }

            function addEventListenerToUploadLocalStorageItem(selector, arr, callback) {
                arr.forEach(function(event) {
                    document.querySelector(selector).addEventListener(event, callback, false);
                });
            }

            setGetFromLocalStorage(['.media-resolutions', '.media-framerates', '.media-bitrates', '.recording-media', '.media-container-format']);

            function getVideoResolutions(mediaConstraints) {
                if(!mediaConstraints.video) {
                    return mediaConstraints;
                }

                var select = document.querySelector('.media-resolutions');
                var value = select.value;

                if(value == 'default') {
                    return mediaConstraints;
                }

                value = value.split('x');

                if(value.length != 2) {
                    return mediaConstraints;
                }

                defaultWidth = parseInt(value[0]);
                defaultHeight = parseInt(value[1]);

                if(DetectRTC.browser.name === 'Firefox') {
                    mediaConstraints.video.width = defaultWidth;
                    mediaConstraints.video.height = defaultHeight;
                    return mediaConstraints;
                }

                if(!mediaConstraints.video.mandatory) {
                    mediaConstraints.video.mandatory = {};
                    mediaConstraints.video.optional = [];
                }

                var isScreen = recordingMedia.value.toString().toLowerCase().indexOf('screen') != -1;

                if(isScreen) {
                    mediaConstraints.video.mandatory.maxWidth = defaultWidth;
                    mediaConstraints.video.mandatory.maxHeight = defaultHeight;
                }
                else {
                    mediaConstraints.video.mandatory.minWidth = defaultWidth;
                    mediaConstraints.video.mandatory.minHeight = defaultHeight;
                }

                return mediaConstraints;
            }

            function captureUserMedia(mediaConstraints, successCallback, errorCallback) {
                if(mediaConstraints.video == true) {
                    mediaConstraints.video = {};
                }

                setVideoBitrates();

                mediaConstraints = getVideoResolutions(mediaConstraints);
                mediaConstraints = getFrameRates(mediaConstraints);

                var isBlackBerry = !!(/BB10|BlackBerry/i.test(navigator.userAgent || ''));
                if(isBlackBerry && !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia)) {
                    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
                    navigator.getUserMedia(mediaConstraints, successCallback, errorCallback);
                    return;
                }

                navigator.mediaDevices.getUserMedia(mediaConstraints).then(function(stream) {
                    successCallback(stream);

                    setVideoURL(stream, true);
                }).catch(function(error) {
                    if(error && (error.name === 'ConstraintNotSatisfiedError' || error.name === 'OverconstrainedError')) {
                        alert('Your camera or browser does NOT supports selected resolutions or frame-rates. \n\nPlease select "default" resolutions.');
                    }
                    else if(error && error.message) {
                        alert(error.message);
                    }
                    else {
                        alert('Unable to make getUserMedia request. Please check browser console logs.');
                    }

                    errorCallback(error);
                });
            }

            function setMediaContainerFormat(arrayOfOptionsSupported) {
                var options = Array.prototype.slice.call(
                    mediaContainerFormat.querySelectorAll('option')
                );

                var localStorageItem;
                if(localStorage.getItem('media-container-format')) {
                    localStorageItem = localStorage.getItem('media-container-format');
                }

                var selectedItem;
                options.forEach(function(option) {
                    option.disabled = true;

                    if(arrayOfOptionsSupported.indexOf(option.value) !== -1) {
                        option.disabled = false;

                        if(localStorageItem && arrayOfOptionsSupported.indexOf(localStorageItem) != -1) {
                            if(option.value != localStorageItem) return;
                            option.selected = true;
                            selectedItem = option;
                            return;
                        }

                        if(!selectedItem) {
                            option.selected = true;
                            selectedItem = option;
                        }
                    }
                });
            }

            function isMimeTypeSupported(mimeType) {
                if(typeof MediaRecorder === 'undefined') {
                    return false;
                }

                if(typeof MediaRecorder.isTypeSupported !== 'function') {
                    return true;
                }

                return MediaRecorder.isTypeSupported(mimeType);
            }

            recordingMedia.onchange = function() {
                if(recordingMedia.value === 'record-audio') {
                    var recordingOptions = [];
                    
                    if(isMimeTypeSupported('audio/webm')) {
                        recordingOptions.push('opus');
                    }

                    if(isMimeTypeSupported('audio/ogg')) {
                        recordingOptions.push('ogg');
                    }

                    recordingOptions.push('pcm');

                    setMediaContainerFormat(recordingOptions);
                    return;
                }

                var isChrome = !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0);

                var recordingOptions = ['vp8']; // MediaStreamRecorder with vp8

                if(isMimeTypeSupported('video/webm\;codecs=vp9')) {
                    recordingOptions.push('vp9'); // MediaStreamRecorder with vp9
                }

                if(isMimeTypeSupported('video/webm\;codecs=h264')) {
                    recordingOptions.push('h264'); // MediaStreamRecorder with h264
                }

                if(isMimeTypeSupported('video/x-matroska;codecs=avc1')) {
                    recordingOptions.push('mkv'); // MediaStreamRecorder with mkv/matroska
                }

                recordingOptions.push('gif'); // GifRecorder

                if(DetectRTC.browser.name == 'Chrome') {
                    recordingOptions.push('whammy'); // WhammyRecorder
                }

                if(DetectRTC.browser.name == 'Chrome') {
                    recordingOptions.push('WebAssembly'); // WebAssemblyRecorder
                }

                recordingOptions.push('default'); // Default mimeType for MediaStreamRecorder

                setMediaContainerFormat(recordingOptions);
            };
            recordingMedia.onchange();

            if(typeof MediaRecorder === 'undefined' && (DetectRTC.browser.name === 'Edge' || DetectRTC.browser.name === 'Safari')) {
                // webp isn't supported in Microsoft Edge
                // neither MediaRecorder API
                // so lets disable both video/screen recording options

                console.warn('Neither MediaRecorder API nor webp is supported in ' + DetectRTC.browser.name + '. You cam merely record audio.');

                recordingMedia.innerHTML = '<option value="record-audio">Audio</option>';
                setMediaContainerFormat(['pcm']);
            }

            function stringify(obj) {
                var result = '';
                Object.keys(obj).forEach(function(key) {
                    if(typeof obj[key] === 'function') {
                        return;
                    }

                    if(result.length) {
                        result += ',';
                    }

                    result += key + ': ' + obj[key];
                });

                return result;
            }

            function mediaRecorderToStringify(mediaRecorder) {
                var result = '';
                result += 'mimeType: ' + mediaRecorder.mimeType;
                result += ', state: ' + mediaRecorder.state;
                result += ', audioBitsPerSecond: ' + mediaRecorder.audioBitsPerSecond;
                result += ', videoBitsPerSecond: ' + mediaRecorder.videoBitsPerSecond;
                if(mediaRecorder.stream) {
                    result += ', streamid: ' + mediaRecorder.stream.id;
                    result += ', stream-active: ' + mediaRecorder.stream.active;
                }
                return result;
            }

            function getFailureReport() {
                var info = 'RecordRTC seems failed. \n\n' + stringify(DetectRTC.browser) + '\n\n' + DetectRTC.osName + ' ' + DetectRTC.osVersion + '\n';

                if (typeof recorderType !== 'undefined' && recorderType) {
                    info += '\nrecorderType: ' + recorderType.name;
                }

                if (typeof mimeType !== 'undefined') {
                    info += '\nmimeType: ' + mimeType;
                }

                Array.prototype.slice.call(document.querySelectorAll('select')).forEach(function(select) {
                    info += '\n' + (select.id || select.className) + ': ' + select.value;
                });

                if (btnStartRecording.recordRTC) {
                    info += '\n\ninternal-recorder: ' + btnStartRecording.recordRTC.getInternalRecorder().name;
                    
                    if(btnStartRecording.recordRTC.getInternalRecorder().getAllStates) {
                        info += '\n\nrecorder-states: ' + btnStartRecording.recordRTC.getInternalRecorder().getAllStates();
                    }
                }

                if(btnStartRecording.stream) {
                    info += '\n\naudio-tracks: ' + getTracks(btnStartRecording.stream, 'audio').length;
                    info += '\nvideo-tracks: ' + getTracks(btnStartRecording.stream, 'video').length;
                    info += '\nstream-active? ' + !!btnStartRecording.stream.active;

                    btnStartRecording.stream.getTracks().forEach(function(track) {
                        info += '\n' + track.kind + '-track-' + (track.label || track.id) + ': (enabled: ' + !!track.enabled + ', readyState: ' + track.readyState + ', muted: ' + !!track.muted + ')';

                        if(track.getConstraints && Object.keys(track.getConstraints()).length) {
                            info += '\n' + track.kind + '-track-getConstraints: ' + stringify(track.getConstraints());
                        }

                        if(track.getSettings && Object.keys(track.getSettings()).length) {
                            info += '\n' + track.kind + '-track-getSettings: ' + stringify(track.getSettings());
                        }
                    });
                }

                if(timeSlice && btnStartRecording.recordRTC) {
                    info += '\ntimeSlice: ' + timeSlice;

                    if(btnStartRecording.recordRTC.getInternalRecorder().getArrayOfBlobs) {
                        var blobSizes = [];
                        btnStartRecording.recordRTC.getInternalRecorder().getArrayOfBlobs().forEach(function(blob) {
                            blobSizes.push(blob.size);
                        });
                        info += '\nblobSizes: ' + blobSizes;
                    }
                }

                else if(btnStartRecording.recordRTC && btnStartRecording.recordRTC.getBlob()) {
                    info += '\n\nblobSize: ' + bytesToSize(btnStartRecording.recordRTC.getBlob().size);
                }

                if(btnStartRecording.recordRTC && btnStartRecording.recordRTC.getInternalRecorder() && btnStartRecording.recordRTC.getInternalRecorder().getInternalRecorder && btnStartRecording.recordRTC.getInternalRecorder().getInternalRecorder()) {
                    info += '\n\ngetInternalRecorder: ' + mediaRecorderToStringify(btnStartRecording.recordRTC.getInternalRecorder().getInternalRecorder());
                }

                return info;
            }

            function saveToDiskOrOpenNewTab(recordRTC) {
                if(!recordRTC.getBlob().size) {
                    var info = getFailureReport();
                    console.log('blob', recordRTC.getBlob());
                    console.log('recordrtc instance', recordRTC);
                    console.log('report', info);

                    if(mediaContainerFormat.value !== 'default') {
                        alert('RecordRTC seems failed recording using ' + mediaContainerFormat.value + '. Please choose "default" option from the drop down and record again.');
                    }
                    else {
                        alert('RecordRTC seems failed. Unexpected issue. You can read the email in your console log. \n\nPlease report using disqus chat below.');
                    }

                    if(mediaContainerFormat.value !== 'vp9' && DetectRTC.browser.name === 'Chrome') {
                        alert('Please record using VP9 encoder. (select from the dropdown)');
                    }
                }

                var fileName = getFileName(fileExtension);

                document.querySelector('#save-to-disk').parentNode.style.display = 'block';
                document.querySelector('#save-to-disk').onclick = function() {
                    if(!recordRTC) return alert('No recording found.');

                    var file = new File([recordRTC.getBlob()], fileName, {
                        type: mimeType
                    });

                    invokeSaveAsDialog(file, file.name);
                };

                document.querySelector('#open-new-tab').onclick = function() {
                    if(!recordRTC) return alert('No recording found.');

                    var file = new File([recordRTC.getBlob()], fileName, {
                        type: mimeType
                    });

                    window.open(URL.createObjectURL(file));
                };

                // upload to PHP server
                if(isMyOwnDomain()) {
                    document.querySelector('#upload-to-php').disabled = true;
                    document.querySelector('#upload-to-php').style.display = 'none';
                }
                else {
                    document.querySelector('#upload-to-php').disabled = false;
                }
                
                document.querySelector('#upload-to-php').onclick = function() {
                    if(isMyOwnDomain()) {
                        alert('PHP Upload is not available on this domain.');
                        return;
                    }

                    if(!recordRTC) return alert('No recording found.');
                    this.disabled = true;

                    var button = this;
                    uploadToPHPServer(fileName, recordRTC, function(progress, fileURL) {
                        if(progress === 'ended') {
                            button.disabled = false;
                            button.innerHTML = 'Click to download from server';
                            button.onclick = function() {
                                SaveFileURLToDisk(fileURL, fileName);
                            };

                            setVideoURL(fileURL);

                            var html = 'Uploaded to PHP.<br>Download using below link:<br>';
                            html += '<a href="'+fileURL+'" download="'+fileName+'" style="color: yellow; display: block; margin-top: 15px;">'+fileName+'</a>';
                            recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = html;
                            return;
                        }
                        button.innerHTML = progress;
                        recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = progress;
                    });
                };

                // upload to YouTube!
                document.querySelector('#upload-to-youtube').disabled = false;
                document.querySelector('#upload-to-youtube').onclick = function() {
                    if(!recordRTC) return alert('No recording found.');
                    this.disabled = true;

                    if(isLocalHost()) {
                        alert('This feature is NOT available on localhost.');
                        return;
                    }

                    if(isMyOwnDomain() === false) {
                        var url = 'https://github.com/muaz-khan/RecordRTC/wiki/Upload-to-YouTube';
                        alert('YouTube API key is configured to work only on webrtc-experiment.com. Please create your own YouTube key + oAuth client-id and use it instead.\n\nWiki page: ' + url);

                        // check instructions on the wiki page
                        location.href = url;
                        return;
                    }

                    var button = this;
                    uploadToYouTube(fileName, recordRTC, function(percentageComplete, fileURL) {
                        if(percentageComplete == 'uploaded') {
                            button.disabled = false;
                            button.innerHTML = 'Uploaded. However YouTube is still processing.';
                            button.onclick = function() {
                                window.open(fileURL);
                            };
                            return;
                        }
                        if(percentageComplete == 'processed') {
                            button.disabled = false;
                            button.innerHTML = 'Uploaded & Processed. Click to open YouTube video.';
                            button.onclick = function() {
                                window.open(fileURL);
                            };

                            document.querySelector('h1').innerHTML = 'Your video has been uploaded.';
                            window.scrollTo(0, 0);

                            alert('Your video has been uploaded.');
                            return;
                        }
                        if(percentageComplete == 'failed') {
                            button.disabled = false;
                            button.innerHTML = 'YouTube failed transcoding the video.';
                            button.onclick = function() {
                                window.open(fileURL);
                            };
                            return;
                        }
                        button.innerHTML = percentageComplete + '% uploaded to YouTube.';
                    });
                };
            }

            function uploadToPHPServer(fileName, recordRTC, callback) {
                var blob = recordRTC instanceof Blob ? recordRTC : recordRTC.getBlob();
                
                blob = new File([blob], getFileName(fileExtension), {
                    type: mimeType
                });

                // create FormData
                var formData = new FormData();
                formData.append('video-filename', fileName);
                formData.append('video-blob', blob);

                callback('Uploading recorded-file to server.');

                // var upload_url = 'https://your-domain.com/files-uploader/';
                var upload_url = 'RecordRTC-to-PHP/save.php';

                // var upload_directory = upload_url;
                var upload_directory = 'RecordRTC-to-PHP/uploads/';

                makeXMLHttpRequest(upload_url, formData, function(progress) {
                    if (progress !== 'upload-ended') {
                        callback(progress);
                        return;
                    }

                    callback('ended', upload_directory + fileName);
                });
            }

            function makeXMLHttpRequest(url, data, callback) {
                var request = new XMLHttpRequest();
                request.onreadystatechange = function() {
                    if (request.readyState == 4 && request.status == 200) {
                        if(request.responseText === 'success') {
                            callback('upload-ended');
                            return;
                        }

                        document.querySelector('.header').parentNode.style = 'text-align: left; color: red; padding: 5px 10px;';
                        document.querySelector('.header').parentNode.innerHTML = request.responseText;
                    }
                };

                request.upload.onloadstart = function() {
                    callback('Upload started...');
                };

                request.upload.onprogress = function(event) {
                    callback('Upload Progress ' + Math.round(event.loaded / event.total * 100) + "%");
                };

                request.upload.onload = function() {
                    callback('progress-about-to-end');
                };

                request.upload.onload = function() {
                    callback('Getting File URL..');
                };

                request.upload.onerror = function(error) {
                    callback('Failed to upload to server');
                };

                request.upload.onabort = function(error) {
                    callback('Upload aborted.');
                };

                request.open('POST', url);
                request.send(data);
            }

            function getRandomString() {
                if (window.crypto && window.crypto.getRandomValues && navigator.userAgent.indexOf('Safari') === -1) {
                    var a = window.crypto.getRandomValues(new Uint32Array(3)),
                        token = '';
                    for (var i = 0, l = a.length; i < l; i++) {
                        token += a[i].toString(36);
                    }
                    return token;
                } else {
                    return (Math.random() * new Date().getTime()).toString(36).replace(/\./g, '');
                }
            }

            function getFileName(fileExtension) {
                var d = new Date();
                var year = d.getUTCFullYear();
                var month = d.getUTCMonth();
                var date = d.getUTCDate();
                return 'RecordRTC-' + year + month + date + '-' + getRandomString() + '.' + fileExtension;
            }

            function SaveFileURLToDisk(fileUrl, fileName) {
                var hyperlink = document.createElement('a');
                hyperlink.href = fileUrl;
                hyperlink.target = '_blank';
                hyperlink.download = fileName || fileUrl;

                (document.body || document.documentElement).appendChild(hyperlink);
                hyperlink.onclick = function() {
                   (document.body || document.documentElement).removeChild(hyperlink);

                   // required for Firefox
                   window.URL.revokeObjectURL(hyperlink.href);
                };

                var mouseEvent = new MouseEvent('click', {
                    view: window,
                    bubbles: true,
                    cancelable: true
                });

                hyperlink.dispatchEvent(mouseEvent);
            }

            function getURL(arg) {
                var url = arg;

                if(arg instanceof Blob || arg instanceof File) {
                    url = URL.createObjectURL(arg);
                }

                if(arg instanceof RecordRTC || arg.getBlob) {
                    url = URL.createObjectURL(arg.getBlob());
                }

                if(arg instanceof MediaStream || arg.getTracks) {
                    // url = URL.createObjectURL(arg);
                }

                return url;
            }

            function setVideoURL(arg, forceNonImage) {
                var url = getURL(arg);

                var parentNode = recordingPlayer.parentNode;
                parentNode.removeChild(recordingPlayer);
                parentNode.innerHTML = '';

                var elem = 'video';
                if(type == 'gif' && !forceNonImage) {
                    elem = 'img';
                }
                if(type == 'audio') {
                    elem = 'audio';
                }

                recordingPlayer = document.createElement(elem);
                
                if(arg instanceof MediaStream) {
                    recordingPlayer.muted = true;
                }

                recordingPlayer.addEventListener('loadedmetadata', function() {
                    if(navigator.userAgent.toLowerCase().indexOf('android') == -1) return;

                    // android
                    setTimeout(function() {
                        if(typeof recordingPlayer.play === 'function') {
                            recordingPlayer.play();
                        }
                    }, 2000);
                }, false);

                recordingPlayer.poster = '';

                if(arg instanceof MediaStream) {
                    recordingPlayer.srcObject = arg;
                }
                else {
                    recordingPlayer.src = url;
                }

                if(typeof recordingPlayer.play === 'function') {
                    recordingPlayer.play();
                }

                recordingPlayer.addEventListener('ended', function() {
                    url = getURL(arg);
                    
                    if(arg instanceof MediaStream) {
                        recordingPlayer.srcObject = arg;
                    }
                    else {
                        recordingPlayer.src = url;
                    }
                });

                parentNode.appendChild(recordingPlayer);
            }
        </script>

        <script>
            function captureScreen(config) {
                if (navigator.getDisplayMedia) {
                    navigator.getDisplayMedia({
                        video: true
                    }).then(screenStream => {
                        config.onMediaCaptured(screenStream);

                        addStreamStopListener(screenStream, function() {
                            // config.onMediaStopped();

                            btnStartRecording.onclick();
                        });

                        setVideoURL(screenStream, true);
                    }).catch(function(error) {
                        config.onMediaCapturingFailed(error);
                    });
                } else if (navigator.mediaDevices.getDisplayMedia) {
                    navigator.mediaDevices.getDisplayMedia({
                        video: true
                    }).then(screenStream => {
                        config.onMediaCaptured(screenStream);

                        addStreamStopListener(screenStream, function() {
                            // config.onMediaStopped();

                            btnStartRecording.onclick();
                        });

                        setVideoURL(screenStream, true);
                    }).catch(function(error) {
                        config.onMediaCapturingFailed(error);
                    });
                } else {
                    var error = 'getDisplayMedia API are not supported in this browser.';
                    config.onMediaCapturingFailed(error);
                    alert(error);
                }
            }

            function captureAudioPlusScreen(config) {
                if (navigator.getDisplayMedia) {
                    navigator.getDisplayMedia({
                        video: true
                    }).then(screenStream => {
                        navigator.mediaDevices.getUserMedia({audio:true}).then(function(mic) {
                            screenStream.addTrack(mic.getTracks()[0]);

                            config.onMediaCaptured(screenStream);

                            addStreamStopListener(screenStream, function() {
                                // config.onMediaStopped();

                                btnStartRecording.onclick();
                            });

                            setVideoURL(screenStream, true);
                        });
                    }).catch(function(error) {
                        config.onMediaCapturingFailed(error);
                    });
                } else if (navigator.mediaDevices.getDisplayMedia) {
                    navigator.mediaDevices.getDisplayMedia({
                        video: true
                    }).then(screenStream => {
                        navigator.mediaDevices.getUserMedia({audio:true}).then(function(mic) {
                            screenStream.addTrack(mic.getTracks()[0]);

                            config.onMediaCaptured(screenStream);

                            addStreamStopListener(screenStream, function() {
                                // config.onMediaStopped();

                                btnStartRecording.onclick();
                            });

                            setVideoURL(screenStream, true);
                        });
                    }).catch(function(error) {
                        config.onMediaCapturingFailed(error);
                    });
                } else {
                    var error = 'getDisplayMedia API are not supported in this browser.';
                    config.onMediaCapturingFailed(error);
                    alert(error);
                }
            }
        </script>

        <script>
            /* upload_youtube_video.js Copyright 2017 Google Inc. All Rights Reserved. */

            function uploadToYouTube(fileName, recordRTC, callback) {
                var blob = recordRTC instanceof Blob ? recordRTC : recordRTC.getBlob();
                
                blob = new File([blob], getFileName(fileExtension), {
                    type: mimeType
                });

                if(!uploadVideo) {
                    alert('YouTube API are not available.');
                    return;
                }

                uploadVideo.callback = callback;
                uploadVideo.uploadFile(fileName, blob);
            }

            var uploadVideo;

            var signinCallback = function (result){
              if(result.access_token) {
                uploadVideo = new UploadVideo();
                uploadVideo.ready(result.access_token);

                document.querySelector('#signinButton').style.display = 'none';
              }
              else {
                // console.error('YouTube error', result);
                // document.querySelector('#upload-to-youtube').style.display = 'none';
              }
            };

            var STATUS_POLLING_INTERVAL_MILLIS = 60 * 1000; // One minute.

            var UploadVideo = function() {
              this.tags = ['recordrtc'];
              this.categoryId = 28; // via: http://stackoverflow.com/a/35877512/552182
              this.videoId = '';
              this.uploadStartTime = 0;
            };


            UploadVideo.prototype.ready = function(accessToken) {
              this.accessToken = accessToken;
              this.gapi = gapi;
              this.authenticated = true;
              false && this.gapi.client.request({
                path: '/youtube/v3/channels',
                params: {
                  part: 'snippet',
                  mine: true
                },
                callback: function(response) {
                  if (!response.error) {
                    // response.items[0].snippet.title -- channel title
                    // response.items[0].snippet.thumbnails.default.url -- channel thumbnail
                  }
                }.bind(this)
              });
            };

            UploadVideo.prototype.uploadFile = function(fileName, file) {
              var metadata = {
                snippet: {
                  title: fileName,
                  description: fileName,
                  tags: this.tags,
                  categoryId: this.categoryId
                },
                status: {
                  privacyStatus: 'public'
                }
              };
              var uploader = new MediaUploader({
                baseUrl: 'https://www.googleapis.com/upload/youtube/v3/videos',
                file: file,
                token: this.accessToken,
                metadata: metadata,
                params: {
                  part: Object.keys(metadata).join(',')
                },
                onError: function(data) {
                  var message = data;
                  try {
                    var errorResponse = JSON.parse(data);
                    message = errorResponse.error.message;
                  } finally {
                    alert(message);
                  }
                }.bind(this),
                onProgress: function(data) {
                  var bytesUploaded = data.loaded;
                  var totalBytes = parseInt(data.total);
                  var percentageComplete = parseInt((bytesUploaded * 100) / totalBytes);

                  uploadVideo.callback(percentageComplete);
                }.bind(this),
                onComplete: function(data) {
                  var uploadResponse = JSON.parse(data);
                  this.videoId = uploadResponse.id;
                  this.videoURL = 'https://www.youtube.com/watch?v=' + this.videoId;
                  uploadVideo.callback('uploaded', this.videoURL);

                  setTimeout(this.pollForVideoStatus, 2000);
                }.bind(this)
              });
              this.uploadStartTime = Date.now();
              uploader.upload();
            };

            UploadVideo.prototype.pollForVideoStatus = function() {
              this.gapi.client.request({
                path: '/youtube/v3/videos',
                params: {
                  part: 'status,player',
                  id: this.videoId
                },
                callback: function(response) {
                  if (response.error) {
                    uploadVideo.pollForVideoStatus();
                  } else {
                    var uploadStatus = response.items[0].status.uploadStatus;
                    switch (uploadStatus) {
                      case 'uploaded':
                        uploadVideo.callback('uploaded', uploadVideo.videoURL);
                        uploadVideo.pollForVideoStatus();
                        break;
                        case 'processed':
                        uploadVideo.callback('processed', uploadVideo.videoURL);
                        break;
                        default:
                        uploadVideo.callback('failed', uploadVideo.videoURL);
                        break;
                    }
                  }
                }.bind(this)
              });
            };

        </script>

        <script>
            /* cors_upload.js Copyright 2015 Google Inc. All Rights Reserved. */

            var DRIVE_UPLOAD_URL = 'https://www.googleapis.com/upload/drive/v2/files/';

            var RetryHandler = function() {
              this.interval = 1000; // Start at one second
              this.maxInterval = 60 * 1000; // Don't wait longer than a minute 
            };

            RetryHandler.prototype.retry = function(fn) {
              setTimeout(fn, this.interval);
              this.interval = this.nextInterval_();
            };

            RetryHandler.prototype.reset = function() {
              this.interval = 1000;
            };

            RetryHandler.prototype.nextInterval_ = function() {
              var interval = this.interval * 2 + this.getRandomInt_(0, 1000);
              return Math.min(interval, this.maxInterval);
            };

            RetryHandler.prototype.getRandomInt_ = function(min, max) {
              return Math.floor(Math.random() * (max - min + 1) + min);
            };

            var MediaUploader = function(options) {
              var noop = function() {};
              this.file = options.file;
              this.contentType = options.contentType || this.file.type || 'application/octet-stream';
              this.metadata = options.metadata || {
                'title': this.file.name,
                'mimeType': this.contentType
              };
              this.token = options.token;
              this.onComplete = options.onComplete || noop;
              this.onProgress = options.onProgress || noop;
              this.onError = options.onError || noop;
              this.offset = options.offset || 0;
              this.chunkSize = options.chunkSize || 0;
              this.retryHandler = new RetryHandler();

              this.url = options.url;
              if (!this.url) {
                var params = options.params || {};
                params.uploadType = 'resumable';
                this.url = this.buildUrl_(options.fileId, params, options.baseUrl);
              }
              this.httpMethod = options.fileId ? 'PUT' : 'POST';
            };

            MediaUploader.prototype.upload = function() {
              var self = this;
              var xhr = new XMLHttpRequest();

              xhr.open(this.httpMethod, this.url, true);
              xhr.setRequestHeader('Authorization', 'Bearer ' + this.token);
              xhr.setRequestHeader('Content-Type', 'application/json');
              xhr.setRequestHeader('X-Upload-Content-Length', this.file.size);
              xhr.setRequestHeader('X-Upload-Content-Type', this.contentType);

              xhr.onload = function(e) {
                if (e.target.status < 400) {
                  var location = e.target.getResponseHeader('Location');
                  this.url = location;
                  this.sendFile_();
                } else {
                  this.onUploadError_(e);
                }
              }.bind(this);
              xhr.onerror = this.onUploadError_.bind(this);
              xhr.send(JSON.stringify(this.metadata));
            };

            MediaUploader.prototype.sendFile_ = function() {
              var content = this.file;
              var end = this.file.size;

              if (this.offset || this.chunkSize) {
                // Only bother to slice the file if we're either resuming or uploading in chunks
                if (this.chunkSize) {
                  end = Math.min(this.offset + this.chunkSize, this.file.size);
                }
                content = content.slice(this.offset, end);
              }

              var xhr = new XMLHttpRequest();
              xhr.open('PUT', this.url, true);
              xhr.setRequestHeader('Content-Type', this.contentType);
              xhr.setRequestHeader('Content-Range', 'bytes ' + this.offset + '-' + (end - 1) + '/' + this.file.size);
              xhr.setRequestHeader('X-Upload-Content-Type', this.file.type);
              if (xhr.upload) {
                xhr.upload.addEventListener('progress', this.onProgress);
              }
              xhr.onload = this.onContentUploadSuccess_.bind(this);
              xhr.onerror = this.onContentUploadError_.bind(this);
              xhr.send(content);
            };

            MediaUploader.prototype.resume_ = function() {
              var xhr = new XMLHttpRequest();
              xhr.open('PUT', this.url, true);
              xhr.setRequestHeader('Content-Range', 'bytes */' + this.file.size);
              xhr.setRequestHeader('X-Upload-Content-Type', this.file.type);
              if (xhr.upload) {
                xhr.upload.addEventListener('progress', this.onProgress);
              }
              xhr.onload = this.onContentUploadSuccess_.bind(this);
              xhr.onerror = this.onContentUploadError_.bind(this);
              xhr.send();
            };

            MediaUploader.prototype.extractRange_ = function(xhr) {
              var range = xhr.getResponseHeader('Range');
              if (range) {
                this.offset = parseInt(range.match(/\d+/g).pop(), 10) + 1;
              }
            };

            MediaUploader.prototype.onContentUploadSuccess_ = function(e) {
              if (e.target.status == 200 || e.target.status == 201) {
                this.onComplete(e.target.response);
              } else if (e.target.status == 308) {
                this.extractRange_(e.target);
                this.retryHandler.reset();
                this.sendFile_();
              }
            };

            MediaUploader.prototype.onContentUploadError_ = function(e) {
              if (e.target.status && e.target.status < 500) {
                this.onError(e.target.response);
              } else {
                this.retryHandler.retry(this.resume_.bind(this));
              }
            };

            MediaUploader.prototype.onUploadError_ = function(e) {
              this.onError(e.target.response); // TODO - Retries for initial upload
            };

            MediaUploader.prototype.buildQuery_ = function(params) {
              params = params || {};
              return Object.keys(params).map(function(key) {
                return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
              }).join('&');
            };

            MediaUploader.prototype.buildUrl_ = function(id, params, baseUrl) {
              var url = baseUrl || DRIVE_UPLOAD_URL;
              if (id) {
                url += id;
              }
              var query = this.buildQuery_(params);
              if (query) {
                url += '?' + query;
              }
              return url;
            };
        </script>

        <script>
            var chkFixSeeking = document.querySelector('#chk-fixSeeking');
            chkFixSeeking.onchange = function() {
                if(this.checked === true) {
                    localStorage.setItem(this.id, 'true');
                }
                else {
                    localStorage.removeItem(this.id);
                }
            };
            if(localStorage.getItem(chkFixSeeking.id) === 'true') {
                chkFixSeeking.checked = true;
            }
        </script>

        <script>
            var chkTimeSlice = document.querySelector('#chk-timeSlice');
            var timeSlice = false;

            if(typeof MediaRecorder === 'undefined') {
                chkTimeSlice.disabled = true;
            }

            chkTimeSlice.addEventListener('change', function() {
                if(chkTimeSlice.checked === true) {
                    var _timeSlice = prompt('Please enter timeSlice in milliseconds e.g. 1000 or 2000 or 3000.', 1000);
                    _timeSlice = parseInt(_timeSlice);
                    if(!_timeSlice || _timeSlice == NaN || typeof _timeSlice === 'undefined') {
                        timeSlice = false;
                        return;
                    }

                    timeSlice = _timeSlice;
                }
                else {
                    timeSlice = false;
                }
            }, false);
        </script>

        <script>
            var btnPauseRecording = document.querySelector('#btn-pause-recording');
            btnPauseRecording.onclick = function() {
                if(!btnStartRecording.recordRTC) {
                    btnPauseRecording.style.display = 'none';
                    return;
                }

                btnPauseRecording.disabled = true;
                if(btnPauseRecording.innerHTML === 'Pause') {
                    btnStartRecording.disabled = true;
                    chkFixSeeking.parentNode.style.display = 'none';
                    btnStartRecording.style.fontSize = '15px';
                    btnStartRecording.recordRTC.pauseRecording();
                    recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = 'Recording status: paused';
                    recordingPlayer.pause();

                    btnPauseRecording.style.fontSize = 'inherit';
                    setTimeout(function() {
                        btnPauseRecording.innerHTML = 'Resume Recording';
                        btnPauseRecording.disabled = false;
                    }, 2000);
                }

                if(btnPauseRecording.innerHTML === 'Resume Recording') {
                    btnStartRecording.disabled = false;
                    chkFixSeeking.parentNode.style.display = 'none';
                    btnStartRecording.style.fontSize = 'inherit';
                    btnStartRecording.recordRTC.resumeRecording();
                    recordingPlayer.parentNode.parentNode.querySelector('h2').innerHTML = '<img src="https://www.webrtc-experiment.com/images/progress.gif">';
                    recordingPlayer.play();

                    btnPauseRecording.style.fontSize = '15px';
                    btnPauseRecording.innerHTML = 'Pause';
                    setTimeout(function() {
                        btnPauseRecording.disabled = false;
                    }, 2000);
                }
            };
        </script>

        <section class="experiment" style="padding: 10px 20px; text-align: center;">
            <a href="https://chrome.google.com/webstore/detail/recordrtc/ndcljioonkecdnaaihodjgiliohngojp" target="_blank">
                <img alt="RecordRTC" src="https://www.webrtc-experiment.com/images/recordrtc-icon.png" style="width: 20px;vertical-align: middle;margin-right: 3px;">
                RecordRTC Google Chrome Extension
            </a>
            <br>
            You can <a href="https://github.com/muaz-khan/Chrome-Extensions/tree/master/screen-recording#call-from-your-own-website">call and use</a> this extension from any website!
        </section>

        <section class="experiment">
            <div id="github-issues"></div>
        </section>

        <section class="experiment">
            <div id="github-commits"></div>
        </section>

        <section class="experiment"><small id="send-message"></small></section>

        <section class="experiment">
            <p style="margin-top: 6px; text-align: center;">
                <a href="https://github.com/muaz-khan/RecordRTC">RecordRTC is Open-Sourced (MIT licensed) on Github!</a>
            </p>
        </section>
    </article>

    <footer>
        <p>
            <a href="https://www.webrtc-experiment.com/">WebRTC Experiments</a> |
            <a href="http://www.muazkhan.com/">Muaz Khan</a> |
            <a href="https://twitter.com/WebRTCWeb">@WebRTCWeb</a> |
            <a href="https://twitter.com/muazkh">@muazkh</a>
        </p>
    </footer>

    <!-- commits.js is useless for you! -->
    <script>
        window.useThisGithubPath = 'muaz-khan/RecordRTC';
    </script>
    <script src="https://www.webrtc-experiment.com/commits.js" async></script>
    <script src="https://apis.google.com/js/client:plusone.js"></script>
</body>

</html>
